home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 October
/
EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso
/
Aminet
/
dev
/
cross
/
dasm202.lha
/
dasm-2.02
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-08
|
19KB
|
935 lines
/*
* MAIN.C
*
* DASM sourcefile
*
* NOTE: must handle mnemonic extensions and expression decode/compare.
*/
#include "asm.h"
#define MAXLINE 256
#define ISEGNAME "code"
void cleanup(char *buf);
MNE *parse(char *buf);
void panic(char *str);
MNE *findmne(char *str);
void clearsegs(void);
void clearrefs(void);
static uword hash1(char *str);
static void outlistfile(void);
uword _fmode = 0; /* was trying to port to 16 bit IBM-PC lattice C */
/* but failed */
ubyte Disable_me;
ubyte StopAtEnd = 0;
char *Extstr;
ubyte Listing = 1;
int
main(int ac, char **av)
{
char buf[MAXLINE];
int pass, i;
MNE *mne;
ulong oldredo = -1;
ulong oldwhy = 0;
ulong oldeval = 0;
addhashtable(Ops);
pass = 1;
if (ac < 2) {
fail:
#if Olaf
puts("DASM V2.02, high level Macro Assembler");
#else
puts("DASM V2.00, high level Macro Assembler");
#endif
puts("(C)Copyright 1988 by Matthew Dillon, All Rights Reserved");
puts("redistributable for non-profit only");
puts("");
puts("DASM sourcefile [options]");
puts(" -f# output format");
puts(" -oname output file");
puts(" -lname list file");
puts(" -sname symbol dump");
puts(" -v# verboseness");
puts(" -Dname=exp define label");
#if Olaf
puts(" -Vname=exp define label as in EQM");
puts(" -< Swap < and > (to be backwards compatible)");
#endif
exit(1);
}
#if Olaf
printf("DASM V2.02, (c)Copyright 1988 Matthew Dillon, All Rights Reserved\n");
#else
printf("DASM V2.00, (c)Copyright 1988 Matthew Dillon, All Rights Reserved\n");
#endif
for (i = 2; i < ac; ++i) {
if (av[i][0] == '-') {
register char *str = av[i]+2;
switch(av[i][1]) {
case 'd':
Xdebug = atoi(str);
break;
#if OlafM
case 'M':
#endif
case 'D':
while (*str && *str != '=')
++str;
if (*str == '=') {
*str = 0;
++str;
}
else {
str = "0";
}
Av[0] = av[i]+2;
#if OlafM
if (av[i][1] == 'M')
v_eqm(str, NULL);
else
#endif
v_set(str, NULL);
break;
case 'f': /* F_format */
F_format = atoi(str);
if (F_format < 1 || F_format > 3)
panic("Illegal format specification");
break;
case 'o': /* F_outfile */
F_outfile = str;
nofile:
if (*str == 0)
panic("need file name for specified option");
break;
case 'l': /* F_listfile */
F_listfile = str;
goto nofile;
case 's': /* F_symfile */
F_symfile = str;
goto nofile;
case 'v': /* F_verbose */
F_verbose = atoi(str);
break;
case 't': /* F_temppath */
F_temppath = str;
break;
#if OlafLt
case '<': /* Swap < and > for stupid compatibility */
SwapLessMore = !SwapLessMore;
break;
#endif
default:
goto fail;
}
continue;
}
goto fail;
}
/* INITIAL SEGMENT */
{
register SEGMENT *seg = (SEGMENT *)permalloc(sizeof(SEGMENT));
seg->name = strcpy(permalloc(sizeof(ISEGNAME)), ISEGNAME);
seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
Csegment = Seglist = seg;
}
/* TOP LEVEL IF */
{
register IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
ifs->file = (INCFILE *)-1;
ifs->flags = IFF_BASE;
ifs->acctrue = 1;
ifs->true = 1;
Ifstack = ifs;
}
nextpass:
Localindex = Lastlocalindex = 0;
#if OlafDol
Localdollarindex = Lastlocaldollarindex = 0;
#endif
_fmode = 0x8000;
FI_temp = fopen(F_outfile, "w");
_fmode = 0;
Fisclear = 1;
if (FI_temp == NULL) {
printf("unable to [re]open '%s'\n", F_outfile);
exit(1);
}
if (F_listfile) {
FI_listfile = fopen(F_listfile, "w");
if (FI_listfile == NULL) {
printf("unable to [re]open '%s'\n", F_listfile);
exit(1);
}
}
pushinclude(av[1]);
while (Incfile) {
for (;;) {
if (Incfile->flags & INF_MACRO) {
if (Incfile->strlist == NULL) {
Av[0] = "";
v_mexit(NULL, NULL);
continue;
}
strcpy(buf, Incfile->strlist->buf);
Incfile->strlist = Incfile->strlist->next;
}
else {
if (fgets(buf, MAXLINE, Incfile->fi) == NULL)
break;
}
cleanup(buf);
++Incfile->lineno;
mne = parse(buf);
if (Av[1][0]) {
if (mne) {
if ((mne->flags & MF_IF) || (Ifstack->true && Ifstack->acctrue))
(*mne->vect)(Av[2], mne);
}
else {
if (Ifstack->true && Ifstack->acctrue) {
printf("unknown mnemonic: '%s'\n", Av[1]);
asmerr(4,0);
}
}
}
else {
if (Ifstack->true && Ifstack->acctrue)
programlabel();
}
if (F_listfile)
outlistfile();
}
while (Reploop && Reploop->file == Incfile)
rmnode((void **)&Reploop, sizeof(REPLOOP));
while (Ifstack->file == Incfile)
rmnode((void **)&Ifstack, sizeof(IFSTACK));
fclose(Incfile->fi);
free(Incfile->name);
--Inclevel;
rmnode((void **)&Incfile, sizeof(INCFILE));
if (Incfile) {
/*
if (F_verbose > 1)
printf("back to: %s\n", Incfile->name);
*/
if (F_listfile)
fprintf(FI_listfile, "------- FILE %s\n", Incfile->name);
}
}
if (F_verbose >= 1) {
SEGMENT *seg;
char *bss;
puts("");
printf("END OF PASS: %d\n", pass);
puts("Segment--- init-pc init-rpc finl-pc finl-rpc");
for (seg = Seglist; seg; seg = seg->next) {
bss = (seg->flags & SF_BSS) ? "[u]" : " ";
printf("%10s %3s ", seg->name, bss);
printf("%s %s ", sftos(seg->initorg, seg->initflags), sftos
(seg->initrorg, seg->initrflags));
printf("%s %s\n", sftos(seg->org, seg->flags), sftos(seg->rorg,
seg->rflags));
}
printf("Reasons: %4ld,%4ld Reasoncode: %08lx\n", Redo, Redo_eval,
Redo_why);
}
if (F_verbose >= 3) {
SYMBOL *sym;
int i;
if (F_verbose == 3)
puts("SYMBOLIST: (Unreferenced and unresolved symbols only)");
else
puts("SYMBOLIST");
for (i = 0; i < SHASHSIZE; ++i) {
for (sym = SHash[i]; sym; sym = sym->next) {
if (F_verbose > 3 || (sym->flags & SYM_UNKNOWN) || !(sym->flags &
SYM_MASREF))
printf("%10s %s\n", sym->name, sftos(sym->value, sym->flags));
}
}
puts("ENDSYMBOLIST");
}
closegenerate();
fclose(FI_temp);
if (FI_listfile)
fclose(FI_listfile);
if (Redo) {
if (Redo == oldredo && Redo_why == oldwhy && Redo_eval == oldeval) {
puts("Error: source is not resolvable.");
if (F_verbose < 2)
puts("re-run with verbose option 2 or higher to determine problem");
exit(1);
}
oldredo = Redo;
oldwhy = Redo_why;
oldeval = Redo_eval;
Redo = 0;
Redo_why = 0;
Redo_eval = 0;
++pass;
if (StopAtEnd) {
printf("Unrecoverable error in pass, aborting assembly!\n");
}
else if (pass > 10) {
printf("More than 10 passes, something *must* be wrong!\n");
exit(1);
}
else {
clearrefs();
clearsegs();
goto nextpass;
}
}
if (F_symfile) {
FILE *fi = fopen(F_symfile, "w");
if (fi) {
register SYMBOL *sym;
puts("dumping symbols...");
for (i = 0; i < SHASHSIZE; ++i) {
for (sym = SHash[i]; sym; sym = sym->next) {
fprintf(fi, "%-15s %s", sym->name, sftos(sym->value, sym->flags));
if (sym->flags & SYM_STRING)
fprintf(fi, " \"%s\"", sym->string);
putc('\n', fi);
}
}
fclose(fi);
}
else {
printf("unable to open symbol dump file '%s'\n", F_symfile);
}
}
return 0;
}
static
void
outlistfile(void)
{
char c;
char true;
char *ptr;
char dot;
int i;
if (Incfile->flags & INF_NOLIST)
return;
c = (Pflags & SF_BSS) ? 'U' : ' ';
true = (Ifstack->true && Ifstack->acctrue) ? ' ' : '-';
ptr = Extstr;
dot = ' ';
if (ptr)
dot = '.';
else
ptr = "";
fprintf(FI_listfile, "%5ld %c%s ",
Incfile->lineno, c, sftos(Plab, Pflags & 7));
for (i = 0; i < Glen && i < 4; ++i)
fprintf(FI_listfile, "%02x ", Gen[i]);
for (; i < 4; ++i)
fwrite(" ", 3, 1, FI_listfile);
fprintf(FI_listfile, "%c%-10s %5s%c%-3s %s\n",
true, Av[0], Av[1], dot, ptr, Av[2]);
Glen = 0;
Extstr = NULL;
}
char *
sftos(long val, int flags)
{
static char buf[64];
static char c;
register char *ptr = (c) ? buf : buf + 32;
c = 1 - c;
sprintf(ptr, "%04lx", val);
if (flags & SYM_UNKNOWN)
strcpy(ptr, "????");
if (flags & SYM_STRING)
strcpy(ptr, "str ");
if (flags & SYM_MACRO)
strcpy(ptr, "eqm ");
strcpy(ptr+4, " ");
if (flags & (SYM_MASREF|SYM_SET)) {
ptr[4] = '(';
ptr[7] = ')';
}
if (flags & (SYM_MASREF))
ptr[5] = 'r';
if (flags & (SYM_SET))
ptr[6] = 's';
return ptr;
}
void
clearsegs(void)
{
register SEGMENT *seg;
for (seg = Seglist; seg; seg = seg->next) {
seg->flags = (seg->flags & SF_BSS) | SF_UNKNOWN;
seg->rflags= seg->initflags = seg->initrflags = SF_UNKNOWN;
}
}
void
clearrefs(void)
{
register SYMBOL *sym;
register int i;
for (i = 0; i < SHASHSIZE; ++i)
for (sym = SHash[i]; sym; sym = sym->next)
sym->flags &= ~SYM_REF;
}
void
cleanup(char *buf)
{
register char *str;
register STRLIST *strlist;
register int arg, add;
for (str = buf; *str; ++str) {
switch(*str) {
case '\n':
case ';':
goto br2;
case TAB:
*str = ' ';
break;
case '\'':
++str;
if (*str == TAB)
*str = ' ';
if (*str == '\n' || *str == 0) {
str[0] = ' ';
str[1] = 0;
}
if (str[0] == ' ')
str[0] = '\x80';
break;
case '\"':
++str;
while (*str && *str != '\"') {
if (*str == ' ')
*str = '\x80';
++str;
}
if (*str != '\"') {
asmerr(0,0);
--str;
}
break;
case '{':
if (Disable_me)
break;
if (Xdebug)
printf("macro tail: '%s'\n", str);
arg = atoi(str+1);
for (add = 0; *str && *str != '}'; ++str)
--add;
if (*str != '}') {
puts("end brace required");
--str;
break;
}
--add;
++str;
if (Xdebug)
printf("add/str: %d '%s'\n", add, str);
for (strlist = Incfile->args; arg && strlist;) {
--arg;
strlist = strlist->next;
}
if (strlist) {
add += strlen(strlist->buf);
if (Xdebug)
printf("strlist: '%s' %ld\n", strlist->buf, (long)strlen(strlist->buf));
if (str + add + strlen(str) + 1 > buf + MAXLINE) {
if (Xdebug)
printf("str %8ld buf %8ld (add/strlen(str)): %d %ld\n", (long)str, (long)buf,
add, (long)strlen(str));
panic("failure1");
}
memmove(str + add, str, strlen(str)+1);
str += add;
if (str - strlen(strlist->buf) < buf)
panic("failure2");
memmove(str - strlen(strlist->buf), strlist->buf, strlen(strlist->buf));
str -= strlen(strlist->buf);
if (str < buf || str >= buf + MAXLINE)
panic("failure 3");
--str; /* for loop increments string */
}
else {
asmerr(7,0);
goto br2;
}
break;
}
}
br2:
while(str != buf && *(str-1) == ' ')
--str;
*str = 0;
}
void
panic(char *str)
{
puts(str);
exit(1);
}
/*
* .dir direct x
* .ext extended x
* .r relative x
* .x index, no offset x
* .x8 index, byte offset x
* .x16 index, word offset x
* .bit bit set/clr
* .bbr bit and branch
* .imp implied (inherent) x
* .b x
* .w x
* .l x
* .u x
*/
void
findext(char *str)
{
Mnext = -1;
Extstr = NULL;
#if OlafDotop
if (str[0] == '.') { /* Allow .OP for OP */
return;
}
#endif
while (*str && *str != '.')
++str;
if (*str) {
*str = 0;
++str;
Extstr = str;
switch(str[0]|0x20) {
case '0':
case 'i':
Mnext = AM_IMP;
switch(str[1]|0x20) {
case 'x':
Mnext = AM_0X;
break;
case 'y':
Mnext = AM_0Y;
break;
case 'n':
Mnext = AM_INDWORD;
break;
}
return;
case 'd':
case 'b':
case 'z':
switch(str[1]|0x20) {
case 'x':
Mnext = AM_BYTEADRX;
break;
case 'y':
Mnext = AM_BYTEADRY;
break;
case 'i':
Mnext = AM_BITMOD;
break;
case 'b':
Mnext = AM_BITBRAMOD;
break;
default:
Mnext = AM_BYTEADR;
break;
}
return;
case 'e':
case 'w':
case 'a':
switch(str[1]|0x20) {
case 'x':
Mnext = AM_WORDADRX;
break;
case 'y':
Mnext = AM_WORDADRY;
break;
default:
Mnext = AM_WORDADR;
break;
}
return;
case 'l':
Mnext = AM_LONG;
return;
case 'r':
Mnext = AM_REL;
return;
case 'u':
Mnext = AM_BSS;
return;
}
}
}
/*
* bytes arg will eventually be used to implement a linked list of free
* nodes.
* Assumes *base is really a pointer to a structure with .next as the first
* member.
*/
void
rmnode(void **base, int bytes)
{
void *node;
if ((node = *base) != NULL) {
*base = *(void **)node;
free(node);
}
}
/*
* Parse into three arguments: Av[0], Av[1], Av[2]
*/
MNE *
parse(char *buf)
{
register int i, j;
MNE *mne = NULL;
i = 0;
j = 1;
#if OlafFreeFormat
/* Skip all initial spaces */
while (buf[i] == ' ')
++i;
#endif
#if OlafHashFormat
/*
* If the first non-space is a ^, skip all further spaces too.
* This means what follows is a label.
* If the first non-space is a #, what follows is a directive/opcode.
*/
while (buf[i] == ' ')
++i;
if (buf[i] == '^') {
++i;
while (buf[i] == ' ')
++i;
} else if (buf[i] == '#') {
buf[i] = ' '; /* label separator */
} else
i = 0;
#endif
Av[0] = Avbuf + j;
while (buf[i] && buf[i] != ' ') {
if (buf[i] == ':') {/*OIS*/
i++;
break; /*OIS*/
}
if ((unsigned char)buf[i] == 0x80)
buf[i] = ' ';
Avbuf[j++] = buf[i++];
}
Avbuf[j++] = 0;
#if OlafFreeFormat
/* Try if the first word is an opcode */
findext(Av[0]);
mne = findmne(Av[0]);
if (mne != NULL) {
/* Yes, it is. So there is no label, and the rest
* of the line is the argument
*/
Avbuf[0] = 0; /* Make an empty string */
Av[1] = Av[0]; /* The opcode is the previous first word */
Av[0] = Avbuf; /* Point the label to the empty string */
} else
#endif
{ /* Parse the second word of the line */
while (buf[i] == ' ')
++i;
Av[1] = Avbuf + j;
while (buf[i] && buf[i] != ' ') {
if ((unsigned char)buf[i] == 0x80)
buf[i] = ' ';
Avbuf[j++] = buf[i++];
}
Avbuf[j++] = 0;
/* and analyse it as an opcode */
findext(Av[1]);
mne = findmne(Av[1]);
}
/* Parse the rest of the line */
while (buf[i] == ' ')
++i;
Av[2] = Avbuf + j;
while (buf[i]) {
if (buf[i] == ' ') {
while(buf[i+1] == ' ')
++i;
}
if ((unsigned char)buf[i] == 0x80)
buf[i] = ' ';
Avbuf[j++] = buf[i++];
}
Avbuf[j] = 0;
return mne;
}
MNE *
findmne(char *str)
{
register int i;
register char c;
register MNE *mne;
char buf[64];
#if OlafDotop
if (str[0] == '.') { /* Allow .OP for OP */
str++;
}
#endif
for (i = 0; (c = str[i]); ++i) {
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
buf[i] = c;
}
buf[i] = 0;
for (mne = MHash[hash1(buf)]; mne; mne = mne->next) {
if (strcmp(buf, mne->name) == 0)
break;
}
return(mne);
}
void
v_macro(char *str, MNE *dummy)
{
STRLIST *base;
ubyte defined = 0;
register STRLIST **slp, *sl;
register MACRO *mac;
register MNE *mne;
register uword i;
char buf[MAXLINE];
ubyte skipit = !(Ifstack->true && Ifstack->acctrue);
if (skipit) {
defined = 1;
}
else {
defined = (findmne(str) != NULL);
if (F_listfile)
outlistfile();
}
if (!defined) {
base = NULL;
slp = &base;
mac = (MACRO *)permalloc(sizeof(MACRO));
i = hash1(str);
mac->next = (void *)MHash[i];
mac->vect = v_execmac;
mac->name = strcpy(permalloc(strlen(str)+1), str);
mac->flags = MF_MACRO;
MHash[i] = (void *)mac;
}
while (fgets(buf, MAXLINE, Incfile->fi)) {
++Incfile->lineno;
Disable_me = 1;
cleanup(buf);
Disable_me = 0;
mne = parse(buf);
if (Av[1][0]) {
if (mne && mne->vect == v_endm) {
if (!defined)
mac->strlist = base;
return;
}
}
if (!skipit && F_listfile)
outlistfile();
if (!defined) {
sl = (STRLIST *)permalloc(5+strlen(buf));
strcpy(sl->buf, buf);
*slp = sl;
slp = &sl->next;
}
}
asmerr(8,1);
}
void
addhashtable(MNE *mne)
{
register int i, j;
ubyte opcode[NUMOC];
for (; mne->vect; ++mne) {
memcpy(opcode, mne->opcode, NUMOC);
for (i = j = 0; i < NUMOC; ++i) {
mne->opcode[i] = 0; /* not really needed */
if (mne->okmask & (1 << i))
mne->opcode[i] = opcode[j++];
}
i = hash1(mne->name);
mne->next = MHash[i];
MHash[i] = mne;
}
}
static uword
hash1(char *str)
{
register uword result = 0;
while (*str)
result = (result << 2) ^ *str++;
return(result & MHASHAND);
}
int
pushinclude(char *str)
{
register INCFILE *inf;
register FILE *fi;
if ((fi = fopen(str, "r")) != NULL) {
if (F_verbose > 1)
printf("%.*sInclude: %s\n", Inclevel*4, "", str);
++Inclevel;
if (F_listfile)
fprintf(FI_listfile, "------- FILE %s\n", str);
inf = (INCFILE *)zmalloc(sizeof(INCFILE));
inf->next = Incfile;
inf->name = strcpy(malloc(strlen(str)+1), str);
inf->fi = fi;
inf->lineno = 0;
Incfile = inf;
return(1);
}
printf("unable to open %s\n", str);
return 0;
}
char Stopend[] = {
1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1
};
char *Errors[] = {
"Syntax Error",
"Expression table overflow",
"Unbalanced Braces []",
"Division by zero",
"Unknown Mnemonic",
"Illegal Addressing mode",
"Illegal forced Addressing mode", /* nu */
"Not enough args passed to Macro",
"Premature EOF",
"Illegal character",
"Branch out of range",
"ERR pseudo-op encountered",
"Origin Reverse-indexed", /* 12 */
"EQU: Value mismatch",
"Address must be <$100", /* nu */
"Illegal bit specification",
"Not enough args", /* 16 */
"Label Mismatch", /* 17 */
"Value Undefined",
"Illegal Forced Address mode", /* 19 */
"Processor not supported", /* 20 */
NULL
};
void
asmerr(int err, int abort)
{
char *str;
INCFILE *incfile;
if (Stopend[err])
StopAtEnd = 1;
for (incfile = Incfile; incfile->flags & INF_MACRO; incfile=incfile->next);
str = Errors[err];
if (F_listfile)
fprintf(FI_listfile, "*line %4ld %-10s %s\n", incfile->lineno,
incfile->name, str);
printf("line %4ld %-10s %s\n", incfile->lineno, incfile->name, str);
if (abort) {
puts("Aborting assembly");
if (F_listfile)
fputs("Aborting assembly\n", FI_listfile);
exit(1);
}
}
char *
zmalloc(int bytes)
{
char *ptr = malloc(bytes);
if (ptr) {
memset(ptr, 0, bytes);
return(ptr);
}
panic("unable to malloc");
return NULL;
}
char *
permalloc(int bytes)
{
static char *buf;
static int left;
char *ptr;
/* Assume sizeof(union align) is a power of 2 */
union align {
long l;
void *p;
void (*fp)(void);
};
bytes = (bytes + sizeof(union align)-1) & ~(sizeof(union align)-1);
if (bytes > left) {
if ((buf = malloc(ALLOCSIZE)) == NULL)
panic("unable to malloc");
memset(buf, 0, ALLOCSIZE);
left = ALLOCSIZE;
if (bytes > left)
panic("software error");
}
ptr = buf;
buf += bytes;
left -= bytes;
return(ptr);
}